#ifndef FUNCTIONS_H
#define FUNCTIONS_H

#include <algorithm>
#include <functional>
#include <vector>
#include "types.h"
#include "node.h"
#include "tile.h"
#include "constants.h"

double distance(int x1, int y1, int x2, int y2);

short x_to_tile(float x);

short y_to_tile(float y);

int tile_to_x(short x);

int tile_to_y(short y);

bool line_of_sight(int x1, int y1, int x2, int y2);

std::vector<position> find_path(int startX, int startY, int flagX, int flagY, bool full);

bool set_tiles(Tile *tiles[][MAP_WIDTH], std::string filename);

struct DereferenceCompareNode : public std::binary_function<Node, Node, bool>
{
    bool operator()(const Node lhs, const Node rhs) const
    {
        return lhs.f > rhs.f;
    }
};

template <class T, class Compare> class PQV : public std::vector<T> {
    private:
        Compare comp;
        bool sorted;
        void assureHeap() {
            if (sorted) {
                make_heap(this->begin(),this->end(), comp);
                sorted = false;
            }
        }
    public:
        PQV(Compare cmp = Compare()) : comp(cmp) {
            make_heap(this->begin(),this->end(), comp);
            sorted = false;
        }

        const T& top() {
            assureHeap();
            return this->front();
        }

        void push(const T& x) {
            assureHeap();
            this->push_back(x);
            push_heap(this->begin(),this->end(), comp);
        }

        void pop() {
            assureHeap();
            pop_heap(this->begin(),this->end(), comp);
            this->pop_back();
        }

        void sort() {
            if(not sorted) {
                sort_heap(this->begin(),this->end(), comp);
                //reverse(this->begin(),this->end());
                sorted = true;
            }
        }
};

#endif // FUNCTIONS_H
